#include "animation_commands.h"
#include "media/ianimation.h"
#include "core/inspector.h"

using namespace Commands;
using namespace Commands::Core;

//-----------------------------------------------------------------------------
SetCurrentFrame::SetCurrentFrame()
: Command<IAnimation>(0l)
, frame(0)
{}
//-----------------------------------------------------------------------------
SetCurrentFrame::SetCurrentFrame(size_t frame)
: Command<IAnimation>(0l)
, frame(frame)
{}
//-----------------------------------------------------------------------------
float SetCurrentFrame::Execute(const float)
{
    if(IAnimation* animation = GetObject())
    {
        animation->SetCurrentFrame(frame);
    }
    return 0.0;
}
//-----------------------------------------------------------------------------
bool SetCurrentFrame::IsFinished(void) const
{
    return true;
}
//-----------------------------------------------------------------------------
SetCurrentFrame::~SetCurrentFrame()
{}
//-----------------------------------------------------------------------------
SetCurrentFrame* SetCurrentFrame::Copy(void) const
{
    return new SetCurrentFrame(frame);
}
//-----------------------------------------------------------------------------
void SetCurrentFrame::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
StartAnimate::StartAnimate()
: Command<IAnimation>(0l)
, frameSwitchDelay(0.020f)
, animatingFrames(0)
, animatingFramesDefined(false)
, isFirstCall(true)
, isFinished(false)
, elapsedTime(0.0f)
, switchedFrames(0)
{}
//-----------------------------------------------------------------------------
StartAnimate::StartAnimate(float frameSwitchDelay)
: Command<IAnimation>(0l)
, frameSwitchDelay(frameSwitchDelay)
, animatingFrames(0)
, animatingFramesDefined(false)
, isFirstCall(true)
, isFinished(false)
, elapsedTime(0.0f)
, switchedFrames(0)
{}
//-----------------------------------------------------------------------------
StartAnimate::StartAnimate(float frameSwitchDelay, int animatingFrames)
: Command<IAnimation>(0l)
, frameSwitchDelay(frameSwitchDelay)
, animatingFrames(animatingFrames)
, animatingFramesDefined(true)
, isFirstCall(true)
, isFinished(false)
, elapsedTime(0.0f)
, switchedFrames(0)
{}
//-----------------------------------------------------------------------------
float StartAnimate::Execute(const float seconds)
{
    if(IAnimation* animation = GetObject())
    {
        if(isFirstCall)
        {
            switchedFrames = 0;
            elapsedTime = 0.0f;

            if(!animatingFramesDefined)
            {
                animatingFrames = animation->GetFramesCount() - animation->GetCurrentFrame() - 1;
            }

            isFirstCall = false;
            isFinished = false;
        }

        float currentTime = elapsedTime + seconds;

        if((currentTime >= frameSwitchDelay))
        {
            if(animation->GetCurrentFrame() == (animation->GetFramesCount() - 1) || switchedFrames == animatingFrames)
            {
                isFinished = true;
                isFirstCall = true;
                return frameSwitchDelay - elapsedTime;// = seconds - (elapsedTime + seconds - frameSwitchDelay)
            }

            //         
            while(currentTime >= frameSwitchDelay)
            {
                if(animation->GetCurrentFrame() == (animation->GetFramesCount() - 1) || switchedFrames == animatingFrames)
                {
                    isFinished = true;
                    isFirstCall = true;
                    return seconds - currentTime + frameSwitchDelay;
                }

                currentTime -= frameSwitchDelay;
                animation->NextFrame();
                switchedFrames++;
            }
            elapsedTime = currentTime;
        }
        else
        {
            elapsedTime += seconds;
        }
    }

    //    
    return seconds;
}
//-----------------------------------------------------------------------------
bool StartAnimate::IsFinished(void) const
{
    return isFinished;
}
//-----------------------------------------------------------------------------
StartAnimate::~StartAnimate()
{}
//-----------------------------------------------------------------------------
StartAnimate* StartAnimate::Copy(void) const
{
    if(animatingFramesDefined)
    {
        return new StartAnimate(frameSwitchDelay, animatingFrames);
    }

    return new StartAnimate(frameSwitchDelay);

}
//-----------------------------------------------------------------------------
void StartAnimate::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------

